package ru.gosoplata.service 
{
	import by.blooddy.crypto.Base64;
	import flash.net.SharedObject;
	import flash.utils.ByteArray;
	import ru.gosoplata.model.TmpModel;
	import ru.gosoplata.service.conn.BillAcceptor;
	/**
	 * ...
	 * @author 
	 */
	public class ConfigService 
	{
		static private const _STORAGE_NAME:String = "config";//TODO: переписать на сервис????
		
		private var _callBack:Function;
		private var _atempt:uint=0;
		private var _atempts:uint=2;
		
		private function get soVersion():String 
		{
			var sharedObject:SharedObject = SharedObject.getLocal(_STORAGE_NAME);
			if (!sharedObject) return "0";
			return sharedObject.data.version;
		}
		
		public function ConfigService() 
		{
		}
		//TODO: callBack - временное решение
		/**
		 * Алгоритм работы:
		 * - узнать у EXE версию
		 * - сверить с сохраненной в SharedObject
		 * 					|									|
		 * 				одинаковые							  разные
		 * 		 забираем из SharedObject				  забираем из EXE
		 * 					|									|
		 * 					|							сохраняем в SharedObject
		 * 						\							/
		 * 								распаковываем
		 * 									  |
		 * 									callBack
		 * 
		 * @param	callBack - временное решение, загрузка окончена
		 */
		public function load(callBack:Function):void 
		{
			_callBack = callBack;
			
			if (soVersion != "0") uncompress();
			else chekExeVersion();
		}
		
		public function chekExeVersion():void 
		{
			TmpModel.acceptor.getConfVer(resivedExeVersion);
		}
		
		private function resivedExeVersion(exeVersion:Object):void 
		{
			//TmpModel.debugOutput.add("ConfigService version in SO: " + soVersion + " in Exe: " + exeVersion[BillAcceptor.CONFIG_VERSION]);			
			TmpModel.acceptor.writeLog("ConfigService version in SO: " + soVersion + " in Exe: " + exeVersion[BillAcceptor.CONFIG_VERSION]);
			if (exeVersion[BillAcceptor.CONFIG_VERSION] != soVersion)
			{
				//TmpModel.debugOutput.add("ConfigService буду забирать новую версию из exe : "+exeVersion[BillAcceptor.CONFIG_VERSION]);		
				TmpModel.acceptor.writeLog("ConfigService буду забирать новую версию из exe : "+exeVersion[BillAcceptor.CONFIG_VERSION]);
				//TODO: SharedObject - переписать на LocalStorageServise - должен быть отдельный сервис для работы с локальными данными
				var sharedObject:SharedObject = SharedObject.getLocal(_STORAGE_NAME);
				sharedObject.clear();
				sharedObject.data.version = '0';
				sharedObject.data.parts = '0';
				sharedObject.flush();
			
				TmpModel.acceptor.getConf(1, resivedConfPart);
			}else 
			{
				//TmpModel.debugOutput.add("ConfigService забираю сохраненную в SO версию конфига : " + soVersion);
				TmpModel.acceptor.writeLog("ConfigService забираю сохраненную в SO версию конфига : " + soVersion);
				uncompress();
			}
		}
		/**
		 *  exeConfPart.CONFIG="<config version="549" parts="2" part="1" ratio="12" size="217771" sizec="26994">
									<data xmlns:dt="urn:schemas-microsoft-com:datatypes" dt:dt="bin.base64">7L17cxvJlSf…….zJ2NcjhHA=
									</data>
								</config>"
			version - версия 
			parts - кол-во частей 
			part - текущая запрашиваемая часть 
			ratio - коэф-т сжатия deflate 
			size - размер исходного XML-конфига 
			sizec - размер сжатого XML-конфига 
		 */
		private function resivedConfPart(exeConfPart:Object):void 
		{
			var partXmlContayner:XML = new XML(exeConfPart[BillAcceptor.CONFIG]);
			var part:String = String(partXmlContayner.children()[0]).split("\r\n").join("");
			var sharedObject:SharedObject = SharedObject.getLocal(_STORAGE_NAME);
			
			sharedObject.data['part' + partXmlContayner.@part.toString()] = part;
			sharedObject.flush();
			
			TmpModel.debugOutput.add("ConfigService resivedConfPart : " + partXmlContayner.@part+" from "+partXmlContayner.@parts+" version "+partXmlContayner.@version);
			if (partXmlContayner.@parts == partXmlContayner.@part)
			{
				sharedObject = SharedObject.getLocal(_STORAGE_NAME);
				sharedObject.data.version = partXmlContayner.@version.toString();
				sharedObject.data.parts = partXmlContayner.@parts.toString();
				sharedObject.flush();
				
				TmpModel.debugOutput.add("ConfigService resivedConfPart : все части конфига получены и сохранены локально.");
				
				uncompress();
			}else 
			{
				TmpModel.acceptor.getConf(uint(partXmlContayner.@part) + 1, resivedConfPart);
			}
		}
		
		private function uncompress():void 
		{
			TmpModel.debugOutput.add("ConfigService uncompress : start.");
			//TmpModel.acceptor.writeLog("ConfigService uncompress start. версию конфига : " + soVersion);
			
			try 
			{
				var sharedObject:SharedObject = SharedObject.getLocal(_STORAGE_NAME);
				var parts:uint = uint(sharedObject.data.parts);
				var confBA:ByteArray = new ByteArray();
				for (var i:int = 1; i <= parts; i++) 
				{
					confBA.writeBytes(Base64.decode(sharedObject.data['part' + i]));
				}
				confBA.inflate();
				if(!confBA.length)throw new Error('локально сохраненный config пуст. length:'+confBA.length)
				var confXml:XML = new XML(confBA.readMultiByte(confBA.length, "windows-1251"));
			}catch (err:Error)
			{
				reloadConfig(err.message);
				return;
			}
			//TmpModel.debugOutput.add("ConfigService uncompress : end success.");
			TmpModel.acceptor.writeLog("ConfigService uncompress : end success.");
			if (_callBack!=null) {
				_callBack(confXml);
				_callBack = null;
			}
		}
		
		private function reloadConfig(err:String):void 
		{
			if (_atempt >= _atempts) 
			{
				TmpModel.acceptor.writeLog("ConfigService ERROR: Не удалось получить валидный конфиг с нескольких попыток ("+_atempts+"). Переход на index.");
				if (!CONFIG::debug) {
				TmpModel.screenController.gotoIndexHTML();
				}
				return;
			}
			_atempt++;
			
			var sharedObject:SharedObject = SharedObject.getLocal(_STORAGE_NAME);
			sharedObject.clear();
			sharedObject.data.version = '0';
			sharedObject.data.parts = '';
			sharedObject.flush();
			
			TmpModel.acceptor.writeLog("ConfigService uncompress ERROR: "+err+". sharedObject cleared. Atempt "+_atempt+"/"+_atempts);
			TmpModel.acceptor.getConfVer(resivedExeVersion);
		}
	}
}